package jalgebrava.group.groups;


import static jalgebrava.util.collections.IterableMixins.*;
import jalgebrava.group.Group;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;


class CyclicGroupFactory {

	@SuppressWarnings("unused") // just there to keep EMMA happy
	private final static CyclicGroupFactory instance = new CyclicGroupFactory();
	private CyclicGroupFactory() {
		// hidden
	}
	private final static Map<Integer, Group<Integer>> cache = new HashMap<Integer, Group<Integer>>();
	
	final static Group<Integer> mk(int n) {
		Group<Integer> result;
		
		// look in cache
		result = cache.get(n);
		if (result != null) {
			return result;
		}
		
		result = mkWorker(n);
		// put in cache if smallish
		if (n <= 200) {
			cache.put(n, result);
		}
		
		return result;
	}

	private final static Group<Integer> mkWorker(final int n) {
		final ArrayList<Integer> elements = new ArrayList<Integer>(n);
		for (int i=0;i<n;i++) {
			elements.add(i);
		}
		return new AbstractGroup<Integer>("Z"+n, asImmutable(elements), n) {

			@Override
			public Integer unit() {
				return 0;
			}

			@Override
			public Integer inv(Integer x) {
				return (n-x) % n;
			}

			@Override
			public Integer mul(Integer x, Integer y) {
				return (x+y)%n;
			}

			@Override
			public boolean contains(Integer x) {
				return 0 <= x && x < n;
			}

			
		};
	}
}
